`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2024/09/09 09:26:49
// Design Name: 
// Module Name: uart2device_tx
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////
`include "./sys_parameter.vh"


module uart2device_tx #
(
    parameter UART_CLK_PARAM   = 32'd100_000_000,
    parameter UART_BPS_TX      = 32'd115_200    
)(
    input  wire clk  ,
    input  wire sys_rst_n,

    input  [1*8-1 :0]  status_RF_workMode,
    input  [4*8-1 :0]  status_RF_workFre ,
    input  [16*8-1:0]  status_RF_Att     ,

    output wire uart_txd
);


    // localparam CNT_MAX  = UART_CLK_PARAM/1000;  // 1ms
    localparam CNT_MAX  = UART_CLK_PARAM/2;  // 500ms
    
    localparam UART_TX_DATA_LEN = 16'd24;
    localparam UART_PROTOCOL_BYTE = UART_TX_DATA_LEN + 9;

    ///////////////////////////  定时发送
    reg [31:0] clk_cnt;
    always @ (posedge clk) begin
        if(!sys_rst_n) begin
            clk_cnt <= 32'b0;
        end
        else if(clk_cnt == CNT_MAX) begin
            clk_cnt <= 32'b0;
        end
        else begin
            clk_cnt <= clk_cnt + 1'b1;
        end
    end


    ///////////////////////////     REG
    reg [(UART_TX_DATA_LEN*8)-1:0] uartTxData;
    reg        uartTxEn;

    always @(posedge clk) begin
        if(!sys_rst_n) begin
            uartTxData <= {(UART_TX_DATA_LEN*8){1'b0}};
        end
        else begin
            uartTxData <= {
                            status_RF_Att[00*8+:8],status_RF_Att[01*8+:8],
                            status_RF_Att[02*8+:8],status_RF_Att[03*8+:8],
                            status_RF_Att[04*8+:8],status_RF_Att[05*8+:8],
                            status_RF_Att[06*8+:8],status_RF_Att[07*8+:8],
                            status_RF_Att[08*8+:8],status_RF_Att[09*8+:8],
                            status_RF_Att[10*8+:8],status_RF_Att[11*8+:8],
                            status_RF_Att[12*8+:8],status_RF_Att[13*8+:8],
                            status_RF_Att[14*8+:8],status_RF_Att[15*8+:8],
                            8'h0,
                            8'h0,
                            status_RF_workFre,
                            status_RF_workMode,
                            8'h0
                        };
        end
    end



    always @(posedge clk) begin
        if(!sys_rst_n) begin
            uartTxEn <= 1'b0;
        end
        else if(clk_cnt == CNT_MAX) begin
            uartTxEn <= 1'b1;
        end
        else begin
            uartTxEn <= 1'b0;
        end
    end

    reg uartTxEn_r,uartTxEn_rr;
    always @(posedge clk) begin
        uartTxEn_r  <= uartTxEn  ;
        uartTxEn_rr <= uartTxEn_r;
    end


/////////////////////////// Transmitting

    localparam SEND_ST_IDLE         = 8'b0000_0001;
    localparam SEND_ST_CMD          = 8'b0000_0010;
    localparam SEND_ST_DATA_READY   = 8'b0000_0100;
    localparam SEND_ST_WR_FIFO      = 8'b0000_1000;
    localparam SEND_ST_WR_CHECKSUM  = 8'b0001_0000;

    // wire                             fifo_rst       ;
    wire                             fifo_wr/* synthesis keep */        ;
    wire [8-1:0]                     fifo_din/* synthesis keep */       ;
    wire                             fifo_rd/* synthesis keep */        ;
    wire [8-1:0]                     fifo_dout/* synthesis keep */      ;
    // wire                             fifo_dout_valid;
    wire [6-1:0] fifo_wr_cnt/* synthesis keep */    ;
    // wire [FIFO_DATA_COUNT_WIDTH-1:0] fifo_rd_cnt    ;
    wire                             fifo_empty     ;
 

    reg [7:0] send_curSta,send_nxtSta;

    reg [UART_PROTOCOL_BYTE*8-1:0] data_buf;
    reg [15:0] data_num;
    reg [15:0] dataCnt;

    always @(posedge clk) begin
        if(~sys_rst_n) begin
            send_curSta <= SEND_ST_IDLE;
        end
        else begin
            send_curSta <= send_nxtSta;
        end
    end

    always @(*) begin
        case(send_curSta)
            SEND_ST_IDLE : begin
                send_nxtSta = SEND_ST_CMD;
            end
            SEND_ST_CMD : begin
                if(uartTxEn_r & (~uartTxEn_rr)) begin
                    send_nxtSta = SEND_ST_DATA_READY;
                end
                else begin
                    send_nxtSta = SEND_ST_CMD;
                end
            end
            SEND_ST_DATA_READY : begin
                if(fifo_wr_cnt < 128 - UART_PROTOCOL_BYTE) begin // fifo剩余空间够一包数据
                    send_nxtSta = SEND_ST_WR_FIFO;
                end
                else begin
                    send_nxtSta = SEND_ST_DATA_READY;
                end
            end
            SEND_ST_WR_FIFO : begin
                if(dataCnt + 8'd1 >= data_num) begin //
                    send_nxtSta = SEND_ST_IDLE;
                end
                else begin
                    send_nxtSta = SEND_ST_WR_FIFO;
                end
            end
            // SEND_ST_WR_CHECKSUM : begin
            //     send_nxtSta = SEND_ST_IDLE;
            // end
            default: begin
                send_nxtSta = SEND_ST_IDLE;
            end
        endcase
    end

    always @(posedge clk) begin
        if(~sys_rst_n) begin
            data_buf <= {UART_PROTOCOL_BYTE*8{1'b0}};
            data_num <= 16'b0;
        end
        else begin
            case(send_curSta)
                SEND_ST_IDLE : begin
                    data_buf <= {UART_PROTOCOL_BYTE*8{1'b0}};
                    data_num <= 16'b0;
                end
                SEND_ST_CMD : begin
                    if(uartTxEn_r & (~uartTxEn_rr)) begin
                        data_num <= UART_PROTOCOL_BYTE;
                        {data_buf[8*0 +:8],data_buf[8* 1+:8]} <= `UART_HEAD        ; // HEAD
                        {data_buf[8*3 +:8],data_buf[8* 2+:8]} <= UART_PROTOCOL_BYTE; // LEN
                        {data_buf[8*5 +:8],data_buf[8* 4+:8]} <= `CTRL_BOARD_STATUS; // CMD
                        data_buf[8* 6+:8]                     <= `UART_LOC_ID      ; // SRC_ID
                        data_buf[8* 7+:8]                     <= `UART_DST_ID      ; // DST_ID
                        data_buf[8* 8+:(UART_TX_DATA_LEN*8)]  <= uartTxData        ; // DATA
                        data_buf[(UART_PROTOCOL_BYTE-1)*8+:8] <= 8'hFF             ; // CHECKSUM
                    end
                    else begin
                        data_buf <= {UART_PROTOCOL_BYTE*8{1'b0}};
                        data_num <= 16'b0;
                    end
                end
                SEND_ST_DATA_READY : begin
                    data_num <= data_num;
                    data_buf <= data_buf;
                end
                SEND_ST_WR_FIFO : begin
                    data_num <= data_num;
                    data_buf <= data_buf >>8;
                end
                default: begin
                    data_buf <= {UART_PROTOCOL_BYTE*8{1'b0}};
                end
            endcase
        end
    end

    always @(posedge clk) begin
        if(~sys_rst_n) begin
            dataCnt <= 16'b0;
        end
        else if(send_curSta == SEND_ST_WR_FIFO) begin
            dataCnt <= dataCnt + 1'b1;
        end
        else begin
            dataCnt <= 16'b0;
        end
    end
            

    // assign fifo_rst = ~sys_rst_n;
    assign fifo_wr  = (send_curSta == SEND_ST_WR_FIFO);
    assign fifo_din = (send_curSta == SEND_ST_WR_FIFO)? data_buf[0+:8] : {8{1'b0}};




    // uart_tx_fifo uart_tx_fifo (
    //     .clock           ( clk          ),
    //     .data            ( fifo_din     ),
    //     .rdreq           ( fifo_rd      ),
    //     .wrreq           ( fifo_wr      ),
    //     .empty           ( fifo_empty   ),
    //     .full            (              ),
    //     .q               ( fifo_dout    ),
    //     .usedw           ( fifo_wr_cnt  )
    // );

fifo_generator_0 fifo_generator_0 (
  .clk      (clk        ),     
  .din      (fifo_din   ), 
  .wr_en    (fifo_wr    ), 
  .rd_en    (fifo_rd    ),  
  .dout     (fifo_dout  ),    
  .full     (),              
  .empty    (fifo_empty )  
);

    wire  uart_tx_en;
    wire [7:0] uart_din;
    wire TI;

    assign fifo_rd = uart_tx_en;
    assign uart_tx_en = (~fifo_empty) & (~TI);
    assign uart_din = fifo_dout[0+:8];

    uart_send #(
        .CLK_FREQ( UART_CLK_PARAM   ), //系统时钟频率
        .UART_BPS( UART_BPS_TX      )  //波特率
        )
    uart_send(
        .sys_clk  ( clk             ), //系统时钟
        .sys_rst_n( sys_rst_n       ), //系统复位，低电平有效

        .uart_en  ( uart_tx_en      ), //发送使能
        .uart_din ( uart_din        ), //待发送数据
        .uart_txd ( uart_txd        ), //UART TXD
        .TI       ( TI              )  //发送忙标志
    );



endmodule